// @Author miaoqing
// @Date 2024/02/27 14:04:00
// @Desc
package logic

import (
	"core/common"
	"core/component/function"
	"core/component/idgenerator"
	"core/component/logger"
	"core/component/timer"
	"core/ini"
	"core/network"
	"net"
	"runtime/debug"
	"strconv"
	"sync"
	"sync/atomic"
	"time"
)

var (
	server *Server
	once   sync.Once
)

const (
	httpService     = "pvp-http"
	innerTcpService = "pvp-innertcp"
)

type Server struct {
	network.Service
	id             string
	innerTcpServer *network.TcpServer
	srvID          string
	srvAddr        string
	srvPort        int
	processIdx     int
	conf           *ini.Config
	httpAddr       string
	httpPort       int
	httpHandler    *HTTPHandler
	timer          *timer.Timer
	stopping       atomic.Bool
}

func ServerInstance() *Server {
	once.Do(func() {
		server = &Server{
			innerTcpServer: &network.TcpServer{},
			timer:          timer.NewTimer(),
			httpHandler:    newHttpHandler(),
		}
		server.Impl = server
	})
	return server
}

func (srv *Server) Init(cfg interface{}, processIdx int) {
	c, ok := cfg.(*ini.Config)
	if !ok {
		return
	}
	srv.conf = c
	srv.processIdx = processIdx

	srv.srvPort = c.Server.InnerOnlineTcpPort + processIdx
	srv.srvAddr = c.Server.InnerOnlineTcpIp + ":" + strconv.Itoa(srv.srvPort)
	srv.innerTcpServer.Init(srv.srvAddr)

	srv.httpPort = srv.conf.Server.PvpHttpPort + processIdx
	srv.httpAddr = srv.conf.Server.PvpHttpIp + ":" + strconv.Itoa(srv.httpPort)
	srv.id = strconv.FormatUint(function.IpAddressStringToUint64(srv.httpAddr), 10)

	srv.registerTimer()
	logger.Infof("PvpID:%v pidx:%v", srv.id, processIdx)
}

func (srv *Server) Run() {
	srv.innerTcpServer.NewClient = func(conn net.Conn) network.IConn {
		cli := &OnlineClient{
			NetConn: network.NewNetConn(conn, 512*1024),
		}
		cli.Init()
		cli.Impl = cli
		return cli
	}

	startHTTPServer(srv.httpAddr, srv.httpHandler)

	go srv.innerTcpServer.Run()

	srv.serviceRegister()

	go func() {
		tick := time.NewTicker(time.Second * 1)
		defer func() {
			tick.Stop()
			if err := recover(); err != nil {
				logger.Error("[异常] 全局定时器出错", err, "\n", string(debug.Stack()))
			}
		}()
		for {
			select {
			case <-tick.C:
				srv.timer.Loop()
			}
		}
	}()
}

func (srv *Server) registerTimer() {
	srv.timer.RegTimer(srv.registerPvpServerTimer, 1*time.Second)
}

func (srv *Server) Finialize() {
	srv.stopping.Store(true)
	req := &common.RemoveServerReq{
		ServerID: srv.srvID,
	}
	_ = common.SendCenterHttpRequest(req, nil, "POST", "/removePvpServer")
	srv.innerTcpServer.Close()
	WorldGetMe().FinializeSave()
}

func (srv *Server) serviceRegister() {
	// 注册tcp服务
	srv.srvID = idgenerator.FetchServiceID(innerTcpService, srv.srvAddr)
	logger.Infof("PvpInnerServerID:%v", srv.srvID)
}
